1>npm init -y初始化npm环境

2>在package.json里改一下main（主函数）=>"main": "./bin/www.js",
  bin（一般是可执行文件，我们这里没有可执行文件就写成初次执行的js文件）

3>将初次执行文件（www.js）拆分为server技术文件（www.js）和业务逻辑文件拆分(app.js)
   a> www.js==>主要写一些server的技术相关，基本功能
   b> app.js==>主要写一些业务逻辑代码，在基本功能上去加深
   c> 测试

4>在终端下载nodemon和cross-env  
   a> 下载命令==>npm install nodemon cross-env --save --dev 
   b> nodemon==>监测文件的变化，自动重启node
   c> cross-env==>设置环境变量，兼容mac、linux、windows

5>在package.json里下的scripts添加dev

    a> "dev":"cross-env NODE_ENV=dev nodemon ./bin/www.js",
        1>NODE_ENV=dev ==>当前是在什么环境下开发的，dev是开发环境，有prd即线上环境

    b> "prd":"cross-env NODE_ENV=production nodemon ./bin/www.js" ==>线上环境

    c> 运行用npm run dev
    
6>process
    a> process=>nodejs直接提供的一个全局变量
    b> process.env.NODE_ENV==>识别当前环境是dev（开发）还是production（线上）等环境


7>初始化路由，这里先返回假数据==>将路由与数据分离以符合设计原则。
    通过需求分析，通过路由把接口实现跑通。

    a> 在blog-1下建立一个src==>router=={1、blog.js,2、user.js}
    b> 通过method方法和path来写对应的接口==>先返回普通数据
    c> 在app.js下调用router文件下的两个js文件（也就是写接口文件）
    d> 在app.js下处理路由文件，没有路由文件时写404页面的代码
    e> 优化==>公共数据写改写在app.js里。这里就是path的优化（将path写入req对象中，req.path）
    f> 改写路由文件的path为req.path;
    g> 测试

    路由与数据分离===>app.js只是入口，不适合写很多详细的逻辑，应把更详细的逻辑抽离出去，
        如路由文件==>有blog路由和user路由，将相应的路由代码写入即可。

    这就实现分离==>这就使文件更加清晰和规范化。


8>建立一个数据模型（model文件）和一个controller文件
    a> model文件下写resModel.js文件。一些类对象==>规范数据返回格式模型
    b> 获取url通过get传的值
    c> controller文件下写blog.js在这里面主要是对数据的处理，即每个接口对应的数据（先只写的是list数据）

    www.js==>server    
    app.js==>系统的基本设置
    路由==>逻辑层面
    controller==>数据层了
        从基础到数据转变


9>controller==>写详情页数据
    //文件操作
    postData的讲解==>由于是异步的所有这里用promise
    a> 写个实例讲解==。
    b> 先callback写异步，在promise写
    
10>处理post data
    a> 写个函数封装一下，更好管理，不那么繁琐
    b> 获取到的post的数据放入req对象的body里以方便用

11>写更新博客接口，删除博客接口

12>登录接口，在controller里创建user的数据处理文件

13>数据库demo测试

14>src下新建一个文件夹conf===>db.js==>配置(线上和线下部分)
    a> 通过全局变量process来获取环境的env判断是什么环境以连相应的数据库（线上和线下）
    b> src==>db==>mysql.js==>真正配置数据距库,已经异步处理,最终返回.

15>数据库对接博客列表页
16>数据库对接详情和新建
17>数据库对更新和删除
18>数据库对登录
19>cookie
    1>app.js==>解析cookie
    2>controller==>user.js==>登录验证
    3>user.js==>操作cookie==>res.setHeader
20>cookie限制,防止前端去修改
    1>httpOnly==>只允许后端改，前端不行
    2>expires==>cookie过期时间设置，不允许一直存在;
21>session设置
    1>写一个session数据变量
    2>在cookie中使用userid来对应session数据
    3>检测cookie中是否有userid
    4>对session数据处理及判断
    5>没有userid写上userid，从user.js里复制过来.
13>redis安装
    1>官网下载
    2>启动redis:redis-server.exe redis.windows.conf
    3>服务:redis-cli
    4>在项目下做成工具
14>session写入redis
    redis对应有set和get方法。
    1>app.js==>解析session用redis，
    2>user.js===>session同步到redis.
15>nginx
    nginx下载
    1>配置nginx==>conf==>nginx.conf文件
        location / {
            proxy_pass http://localhost:8002;//前端端口对应页面
        }
        location /api/ {
            proxy_pass http://localhost:5000;//后端端口对应接口
            proxy_set_header Host $host;
        }
16>登录检测
    1>blog.js==>需要的接口用到登录检测.
    2>获取博客列表===>通过前端url传值(isadmin)来检测，强制检测自己的博客文章。

17>日志
    1>文件操作
        
    2>stream写日志
    3>在blog-1下建一个文件logs===>access.log
                             ===>error.log
                             ===>event.log

    4>src下建立一个utils文件===>log.js
        //写日志。
        const fs=require('fs');
        const path=require('path');        
        
        //3.写日志
        function writeLog(writeStream,log){
            writeStream.write(log+'\n');//关键代码；
        }
        
        //1.生成write stream
        function createWriteStream(fileName){
            //获取文件名
            const fullName=path.join(__dirname,'../','../','logs',fileName);
            //创建写入文件流
            const writeStream=fs.createWriteStream(fullName,{
                flags:'a',//追加写入
            });
            return writeStream;
        }
        
        //2.写访问日志
        const accessWriteStream=createWriteStream('access.log');
        function access(log){
            writeLog(accessWriteStream,log);
        }
        
        //
        module.exports={
            access
        }

    5>app.js写入访问日志
    6>utils文件下建立===>copy.sh
        1>  //执行文件
            #!/bin/sh

            //进入写日志目录
            cd /i/30.mooc_nodejs/blog-1/logs  

            //将access.log拷贝并重命名为《$(date + %Y-%m-%d).access.log》
            cp access.log $(date +%Y-%m-%d).access.log;     //date后面需要有空格

            //清空日志(access.log)，继续积累写日志
            echo ''>access.log      
            
        命令行执行copy.sh文件通过===》utils目录下==》sh copy.sh
        max系统可以通过crontab来设置，让其自动在规定的时间执行文件
        
        //linux和max的命名（用于服务端）
        //设置定时任务，
        格式：* * * * * command===========>命令        
        * * * * *===>分钟、小时、天、月份、星期    
        * 0 * * *   command(脚本目录/i/30.mooc_nodejs/blog-1/src/utils/copy.sh) =====>每天0晨执行
        crontab -l===>当前有那些执行任务

        
        2>readline===>逐行读取文件
            const fs=require('fs');
            const path=require('path');
            const readline=require('readline');            
            //文件名
            const fileName=path.join(__dirname,'../','../','logs','access.log');            
            //创建 read stream
            const readStream=fs.createReadStream(fileName);            
            //创建readline(基于stream)对象
            const rl=readline.createInterface({
                input:readStream,
            });            
            let chromeNum=0;
            let sum=0;            
            //逐行读取
            rl.on('line',(lineDate)=>{
                if(!lineDate){
                    return
                }            
                //记录总行数
                sum++;            
                const arr=lineDate.split("--");
                if(arr[2] && arr[2].indexOf('Chrome')>0){
                    //累加chrom数量
                    chromeNum++;
                }
            });           
            //监听读取完成
            rl.on('close',()=>{
                console.log('chrome 占比:'+(chromeNum/sum)*100);
            });